package com.ndood.authenticate.browser;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.social.connect.Connection;
import org.springframework.social.connect.web.ProviderSignInUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.ServletWebRequest;

import com.ndood.core.properties.CommonConstants;
import com.ndood.core.properties.SecurityProperties;
import com.ndood.core.social.SocialController;
import com.ndood.core.social.SocialUserInfo;
import com.ndood.core.support.SimpleResponse;

/**
 * 浏览器自定义身份认证控制类
 * @author ndood
 */
/**
 * 分析AnonymousAuthenticationFilter源码
 * AnonymousAuthenticationFilter 95 判断前面过滤器是否进行过身份认证。如果没有认证则创建一个默认的，authentication principle是一个字符串
 *
 * 分析FilterSecurityInterceptor源码 
 * 访问localhost:8080/user
 * 
 * FilterSecurityInterceptor 90 
 * FilterSecurityInterceptor 111
 * FilterSecurityInterceptor 124 beforeInvocation执行了授权判断逻辑，后面的过滤器实际上进到服务里面去了
 * AbstractSecurityInterceptor 196 
 * DefaultFilterInvocationSecurityMetadataSource 92 读取配置的antMatcher访问权限规则 
 * AbstractSecurityInterceptor 199
 * AbstractSecurityInterceptor 233 投票器决定是否通过，默认的是1个通过全通过affirmative
 * AffirmativeBased 62 循环所有的投票者，springsecurity3只有一个投票者
 * AbstractSecurityInterceptor 235 投票不过，抛出异常。交给ExceptionTranslationFilter处理
 * ExceptionTranslationFilter 132 
 * ExceptionTranslationFilter 172
 * ExceptionTranslationFilter 203 跳转到自定义没权限url /authentication/require
 * 
 * 访问localhost:8080/admin-signIn.html 进行登录 然后重新debug一次
 * AbstractSecurityInterceptor 199 ADMIN->ROLE_ADMIN的原因
 * AbstractSecurityInterceptor 233 
 * AffirmativeBased 62
 */
@RestController
public class BrowserSecurityController extends SocialController {

	/*private Logger logger = LoggerFactory.getLogger(getClass());

	private RequestCache requestCache = new HttpSessionRequestCache();*/

	private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

	@Autowired
	private SecurityProperties securityProperties;

	@Autowired
	private ProviderSignInUtils providerSignInUtils;

	/**
	 * 当需要身份认证时，跳转到这里
	 * 解决ExceptionTranslationFilter 180 如果rememberMe下访问被拒绝不跳转到403，而是跳转到登录页。因为已经登录所以跳转到首页，不够优雅的问题
	 */
	@RequestMapping("/authentication/require")
	@ResponseStatus(code = HttpStatus.UNAUTHORIZED)
	public SimpleResponse requireAuthentication(HttpServletRequest request, HttpServletResponse response)
			throws IOException {

		/*SavedRequest savedRequest = requestCache.getRequest(request, response);
		if (savedRequest != null) {
			String targetUrl = savedRequest.getRedirectUrl();
			logger.info("引发跳转的请求是:" + targetUrl);
			if (StringUtils.endsWithIgnoreCase(targetUrl, ".html")
					||StringUtils.endsWithIgnoreCase(targetUrl, "/")
					||StringUtils.endsWithIgnoreCase(targetUrl, "index")) {
				redirectStrategy.sendRedirect(request, response, securityProperties.getBrowser().getSignInPage());
				return null;
			}else {
				return new SimpleResponse(CommonConstants.FAILUE, "访问的服务需要身份认证，请引导用户到登录页");
			}
		}else {
			return new SimpleResponse(CommonConstants.FAILUE, "访问的服务需要身份认证，请引导用户到登录页；如果您是浏览器访问，请检查cookie是否被禁用");
		}*/
		if(isAjax(request) || isJson(request)) {
			return new SimpleResponse(CommonConstants.FAILUE, "访问的服务需要身份认证，请引导用户到登录页");
		}
		
		//redirectStrategy.sendRedirect(request, response, securityProperties.getBrowser().getSignInPage());
		redirectStrategy.sendRedirect(request, response, "/signOut");
		return null;
	}

	/**
	 * 判断是否是json请求
	 */
	public Boolean isJson(HttpServletRequest request) {
		boolean isJson = request.getHeader("content-type") != null
				&& request.getHeader("content-type").contains("json");
		return isJson;
	}

	/**
	 * 判断是否是ajax请求
	 */
	public static boolean isAjax(HttpServletRequest httpRequest) {
		boolean isAjax = httpRequest.getHeader("X-Requested-With") != null
				&& "XMLHttpRequest".equals(httpRequest.getHeader("X-Requested-With").toString());
		return isAjax;
	}
	
	/**
	 * 
	 * 用户第一次社交登录时，会引导用户进行用户注册或绑定，此服务用于在注册或绑定页面获取社交网站用户信息
	 */
	@GetMapping("/social/user")
	public SocialUserInfo getSocialUserInfo(HttpServletRequest request) {
		Connection<?> connection = providerSignInUtils.getConnectionFromSession(new ServletWebRequest(request));
		return buildSocialUserInfo(connection);
	}

}
